
; Test cases for math instructions

(define-test-suite math-tests "math-tests" (lambda ()
     
  (arith-test + (+) "(+)" 0)
  (arith-test + (+ 3) "(+ 3)" 3)
  (arith-test + (+ 3 4) "(+ 3 4)" 7)
  (arith-test + (+ 3 4 5) "(+ 3 4 5)" 12)
  (arith-test + (+ 1 2 3 4 5 6 7 8 9 10 -50) "(+ 1 2 3 ... 10 -50) = 5" 5)

  (arith-test * (*) "(*)" 1)
  (arith-test * (* 3) "(* 3)" 3)
  (arith-test * (* 3 4) "(* 3 4)" 12)
  (arith-test * (* 3 4 2) "(* 3 4 2)" 24)

  (arith-test - (- -3) "(- -3)" 3)
  (arith-test - (- 3 -4) "(- 3 -4)" 7)

  (arith-test / (/ 1) "(/ 1)" 1)
  (arith-test / (/ 12 4) "(/ 12 4)" 3)

  (arith-test bitwise-ior (bitwise-ior) "(bitwise-ior)" 0)
  (arith-test bitwise-ior (bitwise-ior 5) "(bitwise-ior 5)" 5)
  (arith-test bitwise-ior (bitwise-ior 5 3) "(bitwise-ior 5 3)" 7)
  (arith-test bitwise-ior (bitwise-ior 5 3 16) "(bitwise-ior 5 3 16)" 23)

  (arith-test bitwise-xor (bitwise-xor) "(bitwise-xor)" 0)
  (arith-test bitwise-xor (bitwise-xor 5) "(bitwise-xor 5)" 5)
  (arith-test bitwise-xor (bitwise-xor 5 3) "(bitwise-xor 5 3)" 6)
  (arith-test bitwise-xor (bitwise-xor 5 3 16) "(bitwise-xor 5 3 16)" 22)  

  (arith-test bitwise-and (- (bitwise-and)) "(- (bitwise-and))" 1)
  (arith-test bitwise-and (bitwise-and 5) "(bitwise-and 5)" 5)
  (arith-test bitwise-and (bitwise-and 7 3) "(bitwise-and 7 3)" 3)
  (arith-test bitwise-and (bitwise-and 7 3 17) "(bitwise-and 7 3 17)" 1)

  (arith-test bitwise-not (bitwise-not 31) "(bitwise-not 31)" -32)
  (arith-test bitwise-not (bitwise-not -3) "(bitwise-not -3)" 2)

  (arith-test bit-count (bit-count 31) "(bit-count 31)" 5)
  (arith-test bit-count (bit-count -8) "(bit-count -8)" 3)

  (arith-test arithmetic-shift (arithmetic-shift 0 10) "(arithmetic-shift 0 10)" 0)
  (arith-test arithmetic-shift (arithmetic-shift 1 0) "(arithmetic-shift 1 0)" 1)
  (arith-test arithmetic-shift (arithmetic-shift 1 3) "(arithmetic-shift 1 3)" 8)
  (arith-test arithmetic-shift (arithmetic-shift 32 -3) "(arithmetic-shift 32 -3)" 4)  
  
  (arith-test quotient (quotient 10 3) "(quotient 10 3)" 3)
  (arith-test quotient (quotient 5 1) "(quotient 5 1)" 5)
  (arith-test remainder (remainder 10 3) "(remainder 10 3)" 1)
  (arith-test remainder (remainder 5 1) "(remainder 5 1)" 0)
       
  ; these just raise an exception and let the runtime system handle the calculation
  ; so just check here if the code for them is generated correctly and an exception is raised
  ; the actual arguments do not matter for this test
  ;
  (exception-raise-test exact->inexact (exact->inexact 0) "exact->inexact" (enum op exact->inexact))
  (exception-raise-test inexact->exact (inexact->exact 0) "inexact->exact" (enum op inexact->exact))
  (exception-raise-test exp  (exp 0)    "exp"   (enum op exp))
  (exception-raise-test log  (log 0)    "log"   (enum op log))
  (exception-raise-test sin  (sin 0)    "sin"   (enum op sin))
  (exception-raise-test cos  (cos 0)    "cos"   (enum op cos))
  (exception-raise-test tan  (tan 0)    "tan"   (enum op tan))
  (exception-raise-test asin (asin 0)   "asin"  (enum op asin))
  (exception-raise-test acos (acos 0)   "acos"  (enum op acos))
  (exception-raise-test sqrt (sqrt 0)   "sqrt"  (enum op sqrt))
  (exception-raise-test atan (atan 0)   "atan1" (enum op atan1))  
  (exception-raise-test atan (atan 0 0) "atan2" (enum op atan2))
  (exception-raise-test make-polar       (make-polar 0 0)       "make-polar"       (enum op make-polar))
  (exception-raise-test make-rectangular (make-rectangular 0 0) "make-rectangular" (enum op make-rectangular))

  ; These are implemented for integers only and raise exceptions otherwise
  (bool-test exact?       (exact? 1)      "exact?" #t)
  (arith-test real-part   (real-part 1)   "real-part" 1)
  (arith-test imag-part   (imag-part 1)   "imag-part" 0)
  (arith-test floor       (floor 1)       "floor" 1)
  (arith-test numerator   (numerator 1)   "numerator" 1)
  (arith-test denominator (denominator 1) "denominator" 1)  

  ; these also raise exceptions when faced with doubles or extended numbers
  (bool-test number?   (number? 1) "(number? 1)" #t)
  (bool-test integer?  (integer? 1) "(integer? 1)" #t)
  (bool-test rational? (rational? 1) "(rational? 1)" #t)
  (bool-test real?     (real? 1) "(real? 1)" #t)
  (bool-test complex?  (complex? 1) "(complex? 1)" #t)
  
  (arith-test angle (angle 5) "(angle 5)" 0)
  (arith-test magnitude (magnitude 1) "(magnitude 1)" 1)

  ))